
/* Generated by Interface Builder */

#import "PieView.h"
#import "stdio.h"
#import <dpsclient/wraps.h>
#import <appkit/Font.h>
#import <appkit/Application.h>
#import <appkit/Pasteboard.h>
#import <appkit/Cell.h>
#import <appkit/Matrix.h>
#import <appkit/Slider.h>
#import <appkit/OpenPanel.h>
#import <appkit/Panel.h>
#import <appkit/Control.h>
#import <appkit/Form.h>
#import <strings.h>
#import "slice.h"
#import "math.h"

@implementation PieView

static char logString[10000];

+newFrame:(const NXRect *)tF
{
   int i;
   char buf[4];
   int used;
   FILE *fd;
   
   // we are using the Appkit "newFrame" plus our own additions
   self = [super newFrame:tF];
   
   numDrawSegments = 2;

   gray[0] = .333;
   gray[1] = .666;
   
   strcpy(displayLabel[0],"/");
   strcpy(displayLabel[1],"free");

    /* kludge becuase there is no UNIX documentation on the
     * system call to get disk free space
     */
     
	system("df / | tail -1 | awk '{print $5}' >/tmp/root_space_used");
	fd = (FILE *) openFileReadOnly("/tmp/root_space_used");
    	fgets(buf, 4, fd);
	sscanf(buf, "%d", &used);
	fclose(fd);

   displayValue[0] = (float) used;
   displayValue[1] = (float) (100 - used);
   norm[0] = displayValue[0]*3.6;
   norm[1] = displayValue[1]*3.6;
  

   myFont = [Font newFont:"Helvetica"
                  size:10.0
		  style:0
		  matrix:NX_IDENTITYMATRIX];
		  

   pieSize = 200.0;
   pieFontSize = 10.0;
   openReq = [OpenPanel new];
   c_x = bounds.size.width/2.0;
   c_y = bounds.size.height/2.0;
   [self translate:c_x :c_y];
   return self;
}

- showError: (char *)errorMessage
{
  NXRunAlertPanel("Pie_Matrix", errorMessage,"OK",NULL,NULL);
}

// --------------- methods that respond to user actions start here  --------------

- getValue:sender
{
    int i;
    i = [sender selectedRow];
    displayValue[i] = [sender floatValue];
    // printf("Row = %d  Value = %f\n", i, displayValue[i]);
    [self display];
    return self;
}

- getLabel:sender
{
    int i;
    i = [sender selectedRow];
    strcpy(displayLabel[i],[sender stringValue]);
    // printf("Row = %d  String = %s\n", i, displayLabel[i]);
    [self display];
    return self;
}

- getnSlices:sender
{
    numDrawSegments = [sender intValue];
    [self display];
    return self;
}

- getPieSize:sender
{
    pieSize = [sender floatValue];
	[pieSizeText setFloatValue:pieSize];
    [self display];
    return self;
}

- getPieFontSize:sender
{
    pieFontSize = [sender floatValue];
    myFont = [Font newFont:"Helvetica"
                  size:pieFontSize
		  style:0
		  matrix:NX_IDENTITYMATRIX];
	[pieFontText setFloatValue:pieFontSize];
    [self display];
    return self;
}

- printDisplayList:sender
{
int i;
	printf("Display List:\n");
	for (i=0; i<numDrawSegments; i++) {
		printf("%7.0f  %s\n", displayValue[i], displayLabel[i]);
	}
	return self;
}

- printTree:sender
{
	printf("Tree Structure:\n");
    treeprint(root, 0);
	return self;
}


- openRequest:sender
{
    const char *fileName;
    const char *const types[4] = {NULL,NULL};
    int ok;

    if ([openReq runModalForTypes:types] && (fileName =[openReq filename])) {
	[self openFile:fileName];
    }
    else
	[self showError:"No file chosen or could not open file"];
    return self;
}

- copy:sender { 
   id pb = [NXApp pasteboard];  /* global Pasteboard object */ 
   NXStream  *st;               /* stream to collect data in */ 
   char      *data;             /* actual data buffer */ 
   int       length;            /* length of data */ 
   int       maxLength;         /* (not used here) */

   // To see how to use the pasteboard see page 10-33 of
   // the SysRefMan
   // declare that we will supply a single type of data: PostScript
   [pb declareTypes:&NXPostScriptPboard num:1 owner:self];

   /* get a stream which writes to memory */ 
   st = NXOpenMemory( NULL, 0, NX_WRITEONLY );

   /* write PostScript code for this view into the stream */ 
   [self copyPSCodeInside:NULL to:st];

   /* get actual data buffer from stream */ 
   NXGetMemoryBuffer( st, &data, &length, &maxLength );

   /* write PostScript data to pasteboard */ 
   [pb writeType:NXPostScriptPboard data:data length:length];

   /* deallocate stream, including its buffer */ 
   NXCloseMemory( st, NX_FREEBUFFER );

   return self; 
}


// ---------------- Outlets start here ------------------

- setXForm:anObject
{
    xForm = anObject;
    return self;
}

- setYForm:anObject
{
    yForm = anObject;
    return self;
}

- setPieSizeText:anObject
{
    pieSizeText = anObject;
    return self;
}

- setPieFontText:anObject
{
    pieFontText = anObject;
    return self;
}

-(int) openFile:(const char *)fileName
{
  int i=0;
  char buf[MAX_CHARS_PER_LINE], tmpStr[MAX_CHARS_PER_LINE];
  FILE *input_fp;
  float total=0.0;
  int ret=0;
  
  if (( input_fp = fopen(fileName, "r") ) == NULL ) {
     [self showError:"Could not open file"];
     fprintf(stderr, "File: %s Could not be opened.\n", fileName);
     return NO;
  }

	/* initialize root value of tree */
	root = createNode("/", 0);
	root->stop = NO;
 
 	while (fgets(buf, MAX_CHARS_PER_LINE, input_fp) != NULL) {
    	if (i >= MAX_LINES) {
			printf("Too many lines\n");
			break;
		}
		if (strlen(buf) == 1) {
			printf("Blank Line\n");
			break;
		}
		ret = sscanf(buf, "%f %s", &displayValue[i], displayLabel[i]);
		if (ret == 1) {
			root->word = strdup("/");
			root->value = displayValue[i];
     	} else {
			/* printf("In: %f %s\n", displayValue[i], displayLabel[i]); */
        	addtree(root, displayLabel[i], displayValue[i]);
        	i++;
     	}
  	}
	numDataLines = i;
	printf("%d data points read\n\n", numDataLines);
	fclose(input_fp);
	numDrawSegments = buildDisplayList(root, 0, 0, "/");
	normalize(displayValue, norm, 360, numDrawSegments);
	for (i=0; i<numDrawSegments; i++) {
		angle[i] = norm[i] + total;
		total += norm[i];
	}
	[self display];
	return YES;
}

/* make this view accept first responder so it will understand copy */
-(BOOL)acceptsFirstResponder
{
	return (YES);
}

-resignFirstResponder
{
	return self;
}

- drawSelf:(NXRect*)r :(int)c
{
    int i;
    float total = 0.0;
    c_x = bounds.size.width/2.0 + bounds.origin.x;
    c_y = bounds.size.height/2.0 + bounds.origin.y;
    [self translate:c_x :c_y];
    [myFont set];
    PSsetgray(1.0);
    NXRectFill(&bounds);
    PSsetgray(0.0);
    for (i=0; i<numDrawSegments; i++)
    {
     drawSlice(gray[i], pieSize, total, total+norm[i], pieFontSize, displayLabel[i]);
       total = total + norm[i];
    }
    return self;
}

// mouse handeling starts here

static char logString[10000];

/* add a string to the log and have text updated */
static void addStringLog(target, string)
char *string;
id target;
{
	strcat(logString, string);
	[target setStringValue:logString];
}

/* add an event to the log text */
static void addEventLog(target, string, x, y, type)
char *string;
id target;
float x,y;
int type;
{
static char tmpString[100];
	strcat(logString, string);
	if (type == 1) strcat(logString, " DOWN ");
       else if (type == 2) strcat(logString, " UP ");
          else if (type == 6) strcat(logString, " DRAG ");
             else {
			   sprintf(tmpString, " type=%d ", type);
			   strcat(logString, tmpString);
			 }
	sprintf(tmpString, "at x=%3.0f  y=%3.0f\n", x, y);
	strcat(logString, tmpString);
	[target setStringValue:logString];
}

// from chapter 7 page 61
- mouseDown:(NXEvent *)thisEvent
{
	register int i=0; 
	NXPoint	Loc;
	float mouseAngle, total=0.0;
	Treeptr p;
	
	// printf("click type = %d\n", data.mouse.click);
	Loc = thisEvent->location;
    [self convertPoint:&Loc fromView:nil];
    mouseAngle = 180.0/3.14158*atan(Loc.y/Loc.x);
	if (Loc.x < 0.0)
		mouseAngle = mouseAngle + 180.0;
	if ((Loc.x > 0.0)  && (Loc.y < 0.0))
		mouseAngle = mouseAngle + 360.0;
	while (mouseAngle > angle[i])
	   i++;
	p = locateInTree(root, displayLabel[i]);
	numDrawSegments = buildDisplayList(root, 0, 0, "/");
	normalize(displayValue, norm, 360, numDrawSegments);
	for (i=0; i<numDrawSegments; i++) {
        angle[i] = norm[i] + total;
        total += norm[i];
    }
    [self display];
	return(self); 
}
@end

